package com.visionet.waveletData.web.repository.business.specs;

import com.google.common.collect.Lists;
import com.visionet.waveletData.web.common.utilities.collection.CollectionUtil;
import com.visionet.waveletData.web.common.utilities.string.StringPool;
import com.visionet.waveletData.web.common.utilities.time.DateUtil;
import com.visionet.waveletData.web.entity.account.Role;
import com.visionet.waveletData.web.entity.account.User;
import com.visionet.waveletData.web.service.KeyWord;

import org.apache.commons.lang3.StringUtils;
import org.jsoup.helper.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specification;
import org.springside.modules.persistence.SearchFilter;
import org.springside.modules.utils.Collections3;

import javax.persistence.criteria.*;

import java.util.Collection;
import java.util.Date;
import java.util.List;

public class UserSearchSpecs {
    private static Logger logger = LoggerFactory.getLogger(UserSearchSpecs.class);
	
	public static Specification<User> bySearchFilter(final Collection<SearchFilter> filters) {
		return new Specification<User>() {
			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
				if (Collections3.isNotEmpty(filters)) {

					List<Predicate> predicates = Lists.newArrayList();
					for (SearchFilter filter : filters) {
						
						if("loginName".equals(filter.fieldName)){
							if(StringUtil.isNumeric(filter.value.toString())){
                                predicates.add(builder.or(
                                        builder.like(root.<String>get("loginName"), "%"+filter.value+"%"),
                                        builder.equal(root.<Long>get("userInfo").get("phoneNumber"), filter.value)
                                ));
							}else if(filter.value instanceof String){
								predicates.add(builder.or(
										builder.like(root.<String>get("loginName"), "%"+filter.value+"%"),
										builder.like(root.<String>get("aliasName"), "%"+filter.value+"%"),
                                        builder.equal(root.<String>get("userInfo").get("trueName"), filter.value)
								));
							}
							continue;
						}


                        if("lastLoginTime".equals(filter.fieldName)){
                            if(filter.fieldName == null) continue;

                            if(filter.value.toString().equals(KeyWord.Y)){
                                predicates.add(builder.isNotNull(root.<Date>get("lastLogin")));
                            }else if(filter.value.toString().equals(KeyWord.N)){
                                predicates.add(builder.isNull(root.<Date>get("lastLogin")));
                            }else{
                                try{
                                    predicates.add(builder.greaterThanOrEqualTo(root.<Date>get("lastLogin"),
                                            DateUtil.convertFromString(filter.value.toString(), DateUtil.YMD_FULL)));
                                }catch (Exception e){
                                    logger.error("user query lastLoginTime error:",e);
                                }
                            }
                            continue;
                        }
						
						if("roleIds".equals(filter.fieldName)){	//role集合,组装in语句
							SetJoin<User, Role> roleJoin = root.join(root.getModel().getSet("roleList",Role.class), JoinType.INNER);
							List<Long> roleIds = CollectionUtil.toList(filter.value.toString(), StringPool.COMMA, Long.class);
							
							if(!roleIds.isEmpty()){
								predicates.add(roleJoin.get("id").in(roleIds));
							}
							
							continue;
						}
							
						// nested path translate, 如Task的名为"user.name"的filedName, 转换为Task.user.name属性
						String[] names = StringUtils.split(filter.fieldName, ".");
						Path expression = root.get(names[0]);
						for (int i = 1; i < names.length; i++) {
							expression = expression.get(names[i]);
						}

						// logic operator
						switch (filter.operator) {
						case EQ:
							predicates.add(builder.equal(expression, filter.value));
							break;
						case LIKE:
							predicates.add(builder.like(expression, "%" + filter.value + "%"));
							break;
						case GT:
							predicates.add(builder.greaterThan(expression, (Comparable) filter.value));
							break;
						case LT:
							predicates.add(builder.lessThan(expression, (Comparable) filter.value));
							break;
						case GTE:
							predicates.add(builder.greaterThanOrEqualTo(expression, (Comparable) filter.value));
							break;
						case LTE:
							predicates.add(builder.lessThanOrEqualTo(expression, (Comparable) filter.value));
							break;
						}
					}

					// 将所有条件用 and 联合起来
					if (predicates.size() > 0) {
						return builder.and(predicates.toArray(new Predicate[predicates.size()]));
					}
				}

				return builder.conjunction();
			}
		};
	}
	
	

}
